<!-- 下拉数据过多解决方法 -->
<template>
    <el-select
      :value="value"
      :filter-method="selfFilter"
      filterable
      @visible-change="visibleChange"
      @change="selectChange"
    >
      <el-option
        v-for="item in options"
        :key="item[selectValue]"
        :value="item[selectValue]"
        :label="item[selectLabel]"
      ></el-option>
      <span ref="endOption"></span>
    </el-select>
  </template>
  
  <script>
  export default {
    name: "moreDataSelect",
    props: {
      value: null,
      // 接口拿到的所有数据
      originalList: {
        type: Array,
        default: () => [],
      },
      // 用例进行过滤的字段
      filterLabel: {
        type: String,
        default: "label",
      },
      // 下拉label
      selectLabel: {
        type: String,
        default: "label",
      },
      // 用例进行存储的字段
      selectValue: {
        type: String,
        default: "value",
      },
      // 第一次展示的条数
      showListNum: {
        type: Number,
        default: 10,
      },
      // 一次加载的条数
      loadListNum: {
        type: Number,
        default: 10,
      },
    },
    data() {
      return {
        // 拷贝原生数据
        copyOriginalList: [],
        // 下拉渲染的数据
        options: [],
        // 查询出的所有数据
        filterOption: [],
        // 触底元素
        endEle: null,
        // 用来判断是否为初始化观察者，此时不应该执行列表加载方法
        initObserver: true,
        // 是否处于查询
        isFilter: false,
      };
    },
    mounted() {
      this.$nextTick(() => {
        this.endEle = this.$refs.endOption;
        this.createObserver();
      });
    },
    beforeDestroy() {
      this.delObserver();
    },
    computed: {
      curLength() {
        return this.options.length;
      },
    },
    methods: {
      // 初始化下拉列表
      initList(type) {
        this.isFilter = false;
        this.filterOption = [];
        if (type == "show" && this.value) {
          let index = this.copyOriginalList.findIndex(
            (item) => item[this.selectValue] === this.value
          );
          if (index >= 0) {
            this.copyOriginalList.splice(
              0,
              0,
              this.copyOriginalList.splice(index, 1)[0]
            );
          }
        }
        this.options = this.copyOriginalList.slice(0, this.showListNum);
      },
      // 创建观察器
      createObserver() {
        this.observer = new IntersectionObserver((entries) => {
          entries.forEach((entry) => {
            if (entry.isIntersecting) {
              this.addOption();
            }
          });
        });
        this.observer.observe(this.endEle);
      },
      // 销毁观察者
      delObserver() {
        if (this.observer) {
          this.observer.unobserve(this.endEle);
        }
      },
      selectChange(val) {
        this.$emit("input", val);
      },
      visibleChange() {
        this.initList();
      },
      // 重写过滤方法
      selfFilter(val) {
        if (val) {
          this.isFilter = true;
        } else {
          this.isFilter = false;
          this.options = [];
          this.filterOption = [];
        }
        this.filterOption = this.copyOriginalList.filter((item) =>
          item[this.filterLabel].includes(val)
        );
        this.options = this.filterOption.slice(0, this.showListNum);
      },
      // 到底部新加数据
      addOption() {
        let listArr = [];
        if (this.isFilter) {
          listArr = this.filterOption;
        } else {
          listArr = this.copyOriginalList;
        }
        if (this.options.length < listArr.length) {
          this.options = this.options.concat(
            listArr.slice(this.curLength, this.curLength + this.loadListNum)
          );
        }
      },
    },
    watch: {
      originalList: {
        deep: true,
        immediate: true,
        handler(value) {
          // 将原生数据拷贝到本地
          this.copyOriginalList = JSON.parse(JSON.stringify(value));
          this.initList("show");
        },
      },
    },
  };
  </script>
  